using System;
using System.ComponentModel;
using System.Design;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Design;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Windows.Forms.ComponentModel;
using System.Windows.Forms.Design;

namespace Camalon.Drawing.Design
{

	public class MultiLineTextEditor : UITypeEditor 
	{
		private MultiLineTextEditorUI _editorUI = null;

		public override object EditValue (ITypeDescriptorContext context, IServiceProvider provider, object value) 
	{
			if (provider != null) 
			{
				IWindowsFormsEditorService edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
				if (edSvc != null)
				{                 
					if (_editorUI == null) 
					{
						_editorUI = new MultiLineTextEditorUI();
					}
					
					_editorUI.BeginEdit(value);
					
					edSvc.DropDownControl(_editorUI);
	
					object newValue = _editorUI.Value;
					if(_editorUI.EndEdit()) 
					{
						value = newValue;
					}
				}
			}
			return value;
		}

        
		public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) 
		{
			return UITypeEditorEditStyle.DropDown;
		}
        
		public override bool GetPaintValueSupported (ITypeDescriptorContext context) 
		{
			return false;
		}

		private class MultiLineTextEditorUI : TextBox
		{
			//private IWindowsFormsEditorService _editorService;
			private bool _escapePressed;    // Initialized in BeginEdit

            
			internal MultiLineTextEditorUI() 
			{
				InitializeComponent();           
			}
            
			private void InitializeComponent() 
			{
				this.Multiline = true;
				this.WordWrap= true;
				this.BorderStyle = BorderStyle.None;
				this.Multiline = true;
				this.ScrollBars= ScrollBars.Both;
				this.Height = 100;
			}

			protected override void Dispose(bool disposing) 
			{
				if(disposing) 
				{
					// Your cleanup code here
				}
				base.Dispose(disposing);
			}

			protected override bool ProcessDialogKey(Keys keyData) 
			{

				Keys bubbledKeyData = keyData;
                
				if ((keyData & (Keys.Shift | Keys.Alt)) == 0) 
				{
					switch (keyData & Keys.KeyCode) 
					{
						case Keys.Return:
							if((keyData & Keys.Control) == 0) 
							{
								return false;
							} 
							else 
							{
								bubbledKeyData = Keys.Return;
							}
							break;
						case Keys.Escape:
							if((keyData & Keys.Control) == 0) 
							{
								_escapePressed = true;
							}
							break;
					}
				}
				return base.ProcessDialogKey(bubbledKeyData);
			}

			internal object Value 
			{
				get 
				{
					//Debug.Assert(_editing, "Value is only valid between Begin and EndEdit. (Do not want to keep a reference to a large text buffer.)");
					//Debug.Assert(this.Text.IndexOf("\r") == -1, "Carriage return shouldnt be preset in the Text"); 
					string s = this.Text.Replace("\r\n", "\n");

					if( s.Length > 0 && this.Lines.Length > 1)
					{
						s = s.TrimEnd("\n".ToCharArray());
						s += "\n";
					}
					
					return s;


				}
			}
            

			//internal void BeginEdit(IWindowsFormsEditorService editorService, object value) 
			internal void BeginEdit(object value) 
			{
				//_editorService = editorService;
				_escapePressed = false;
				string s = value as String;
				this.Text = s.Replace("\n","\r\n");
			}
            
			internal bool EndEdit() 
			{	
				//_editorService.CloseDropDown();
				//_editorService = null;
				this.Text = null;
				return !_escapePressed;
			}
            


		}
	}
}
